using System;
using System.Collections;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Text;
using System.Windows.Forms;
using ctsu.BaseForms;
using ctsu.Data;
using Microsoft.Practices.EnterpriseLibrary.Data;

using Syncfusion.Windows.Forms.Grid;
using ctsu.Admin.Forms;


namespace ctsu.Admin.BusLogic.CoreLab
{
	class BLCoreLabFormGridTestReferenceEdit : BLCoreLabFormGridBaseImpl
	{
		private bool _isLocation = false;
		public BLCoreLabFormGridTestReferenceEdit(FormGridMeta formGridMeta, GridControl grid, FormInfoBase formInfo, Form form)
			: base(formGridMeta, grid, formInfo, form)
		{

		}

		#region initialize
		public override bool Initialize()
		{
			_btnEditBatch = (Button)Forms.Utils.GetControlByName("btnEditBatch", this._form.Controls);
			_btnRemoveBatch = (Button)Forms.Utils.GetControlByName("btnRemoveBatch", this._form.Controls);
			_btnPrint = (Button)Forms.Utils.GetControlByName("btnPrint", this._form.Controls);
			_btnSave = (Button)Forms.Utils.GetControlByName("btnSave", this._form.Controls);
			_errorControl = (Label)Forms.Utils.GetControlByName("errCtl", this._form.Controls);

			StringBuilder sb = new StringBuilder();
			string sql = "SELECT r.ID, d.Protocol, d.Patient, r.Location, tt.display as Test, " +
				"t.Result, st.display as Sample, r.OutDate, r.Notes " +
				"FROM TestReference r INNER JOIN TestSamples t ON r.ID = t.ID " +
				"INNER JOIN DrawSamples d ON t.DrawSample = d.ID " +
				"INNER JOIN TestType_L tt ON t.TestType = tt.ID " +
				"INNER JOIN SampleType_L st ON d.SampleType = st.ID " +
				" WHERE 1=2";

			try
			{
				this._tableSchema = Forms.Utils.GetTableSchema(null, sql);
				InitializeGridControl();
				/*this is where change loacation differs from check-in
				 _data (table) is initialized here */
				InitializeTable();
				return true;
			}
			catch (Exception ex)
			{
				sb.Append("Could not retrieve grid table schema!");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "Retrieve Grid Data Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
		}

		private void InitializeGridControl()
		{
			this._grid.BeginUpdate();
			//this adds up the total column width
			int totColWidth = 0;

			int col = 1;
			//create the new grid columns			
			this._grid.ColCount = this._formGridMeta.GridColumns.Count;
			foreach (DataColumn dc in this._tableSchema.Columns)
			{
				//get the metadata for this column
				if (!this._formGridMeta.GridColumns.Contains(dc.ColumnName))
					continue;

				FormGridColumnMeta fgcm = (FormGridColumnMeta)this._formGridMeta.GridColumns[dc.ColumnName];
				//store the dataColum in the tag property
				//in the header row
				this._grid[0, col].Tag = dc;
				this._grid[0, col].Text = fgcm.DisplayName;
				GridStyleInfo gsi = this._grid.ColStyles[col];
				gsi.CellType = fgcm.CellType;
				gsi.Enabled = true;

				if (fgcm.CellType == "CheckBox")
				{
					gsi.CheckBoxOptions = new GridCheckBoxCellInfo("1", "0", "", true);
					gsi.TriState = false;
					gsi.CellValueType = typeof(string);
					gsi.CellValue = "0";

				}
				else
				{
					gsi.CellValue = null;
					gsi.CellValueType = Type.GetType(fgcm.DataType);

					if (fgcm.CellType == "ComboBox")
					{
						BindGridColumn(fgcm, gsi);
						gsi.DropDownStyle = GridDropDownStyle.AutoComplete;
						gsi.ReadOnly = false;
					}
				}

				this._grid.ColWidths[col] = fgcm.Width;
				totColWidth += fgcm.Width;
				if (fgcm.IsHidden)
					this._grid.Cols.Hidden[col] = true;
				if (fgcm.ReadOnly)
					gsi.ReadOnly = true;
				col++;
			}

			base.HookGridEvents();

			if (totColWidth < 440)
				this._grid.Width = totColWidth + 60;

			this._grid.ResizeRowsBehavior = GridResizeCellsBehavior.None;
			this._grid.Model.RowHeights.ResizeToFit(GridRangeInfo.Row(0), GridResizeToFitOptions.IncludeHeaders);
			this._grid.EndUpdate();
		}

		private void InitializeTable()
		{
			string sql = "SELECT r.ID, d.Protocol, d.Patient, r.Location, tt.display as Test, " +
				"t.Result, st.display as Sample, r.OutDate, r.Notes " +
				"FROM TestReference r INNER JOIN TestSamples t ON r.ID = t.ID " +
				"INNER JOIN DrawSamples d ON t.DrawSample = d.ID " +
				"INNER JOIN TestType_L tt ON t.TestType = tt.ID " +
				"INNER JOIN SampleType_L st ON d.SampleType = st.ID " +
				" WHERE 1=2";

			//SqlConnection conn = LoginForm.GetSqlConnection();			
			StringBuilder sb = new StringBuilder();
			try
			{
				DataSet ds = DataAccess.GetDataSet(sql);
				_data = ds.Tables[0];
				this._grid.RowCount = 0;
			}
			catch (Exception ex)
			{
				sb.Append("Could not initialize grid table!");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "Initialize Grid Table Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			finally
			{
				//if(conn != null)
				//    conn.Dispose();
			}
		}
		#endregion initialize

		public override void New()
		{
			InitializeTable();
		}

		#region add replace remove
		public override void ReplaceRow(object obj, int row)
		{
			DataRow dr = (DataRow)this._grid[row, 0].Tag;
			ArrayList al = (ArrayList)obj;

			bool[] replaceColumns = (bool[])al[0];
			Sample samp = (Sample)al[1];

			//change all
			if (replaceColumns[0])
			{
				this._grid[row, 4].CellValue = samp.Location;
				AssignChangeToDataRow(row, 4);

				if (samp.OutDate.Ticks > 0)
				{
					this._grid[row, 8].CellValue = samp.OutDate;
					this._grid[row, 8].Format = "MM/dd/yyyy";
				}
				else
					this._grid[row, 8].Text = "";
				AssignChangeToDataRow(row, 8);

				this._grid[row, 9].CellValue = samp.Note;
				AssignChangeToDataRow(row, 9);
			}
			else
			{
				//location
				if (replaceColumns[1])
				{
					this._grid[row, 4].CellValue = samp.Location;
					AssignChangeToDataRow(row, 4);
					if (samp.Location.Length > 0)
					{
						this._grid[row, 8].Text = "";
						AssignChangeToDataRow(row, 8);
					}
				}
				//outdate
				if (replaceColumns[2])
				{
					if (samp.OutDate.Ticks > 0)
					{
						this._grid[row, 8].CellValue = samp.OutDate;
						this._grid[row, 8].Format = "MM/dd/yyyy";
						this._grid[row, 4].CellValue = samp.Location;
						AssignChangeToDataRow(row, 4);
					}
					else
						this._grid[row, 8].Text = "";
					AssignChangeToDataRow(row, 8);

				}

				if (replaceColumns[3])
				{
					this._grid[row, 9].CellValue = samp.Note;
					AssignChangeToDataRow(row, 9);
				}
			}
			this._btnEditBatch.Enabled = true;
			this._btnRemoveBatch.Enabled = true;
			this._btnSave.Enabled = true;
		}

		public override void AddRow(object obj, int row)
		{
			Sample samp = (Sample)obj;
			DataRow dr = _data.NewRow();
			this._data.Rows.Add(dr);

			int rows = ++this._grid.RowCount;

			this._grid[rows, 0].Tag = dr;
			this._grid[rows, 1].CellValue = samp.TestID;
			AssignChangeToDataRow(rows, 1);
			this._grid[rows, 2].CellValue = samp.Protocol;
			this._grid[rows, 2].Tag = samp.ProtocolInfo;
			this._grid[rows, 2].CellTipText = samp.ProtocolInfo.GetToolTip();

			this._grid[rows, 3].CellValue = samp.PatientID;
			this._grid[rows, 3].Tag = samp.PatientInfo;
			this._grid[rows, 3].CellTipText = samp.PatientInfo.GetToolTip();

			this._grid[rows, 4].CellValue = samp.Location;
			AssignChangeToDataRow(rows, 4);
			this._grid[rows, 5].CellValue = samp.TestName;
			this._grid[rows, 6].CellValue = samp.Result;
			this._grid[rows, 7].CellValue = samp.SampleName;

			if (samp.OutDate == CremaConstants.NullDate)
				this._grid[rows, 8].Text = "";
			else
			{
				this._grid[rows, 8].CellValue = samp.OutDate;
				this._grid[rows, 8].Format = "MM/dd/yyyy";
			}
			AssignChangeToDataRow(rows, 8);

			this._grid[rows, 9].CellValue = samp.Note;
			AssignChangeToDataRow(rows, 9);

			base.AddRow(samp, row);
		}
		#endregion add replace remove

		#region save
		public override bool Save(int foreignID, out string message, Database db, DbTransaction trans)
		{
			message = "";
			if (_data == null)
				return true;
			int labelID;
			foreach (DataRow dr in _data.Rows)
			{
				labelID = (int)dr["ID"];
				if (dr.RowState == DataRowState.Added)
				{
					if (!InsertIntoBatch(labelID, foreignID, out message, db, trans))
						return false;
					if (!UpdateRow(dr, foreignID, out message, db, trans))
						return false;
				}
				else if (dr.RowState == DataRowState.Modified)
				{
					if (!UpdateRow(dr, foreignID, out message, db, trans))
						return false;
				}
			}
			return true;
		}

		private bool InsertIntoBatch(int labelID, int batchID, out string message, Database db, DbTransaction trans)
		{
			message = "";
			string sql = "INSERT INTO TestReferenceEditBatchSamples (BatchID,LabelID) " +
				" VALUES(" + batchID + ", " + labelID + ")";

			try
			{
				DbCommand cmd = db.GetSqlStringCommand(sql);
				db.ExecuteNonQuery(cmd, trans);
				//SqlHelper.ExecuteNonQuery(trans, CommandType.Text, sql);				
			}
			catch (Exception ex)
			{
				message = ex.Message;
				return false;
			}
			return true;
		}

		protected override bool UpdateRow(DataRow dr, int foreignID, out string message, Database db, DbTransaction trans)
		{
			message = "";

			//sql update
			string sqlUpdate = "UPDATE TestReference SET OutDate=@OutDate, " +
				"Location=@Location,Notes=@Notes " +
				"WHERE ID=@ID";

			SqlParameter[] aParams = new SqlParameter[4];
			aParams[0] = new SqlParameter("@OutDate", SqlDbType.DateTime, 0, "OutDate");
			aParams[1] = new SqlParameter("@Location", SqlDbType.VarChar, 25, "Location");
			aParams[2] = new SqlParameter("@Notes", SqlDbType.VarChar, 1000, "Notes");
			aParams[3] = new SqlParameter("@ID", SqlDbType.Int, 0, "ID");
			AssignParameters(aParams, dr, foreignID, 0);

			try
			{
				DbCommand cmd = db.GetSqlStringCommand(sqlUpdate);
				DataAccess.AddParamArrayToDbCommand(cmd, aParams);

				db.ExecuteNonQuery(cmd, trans);
			}
			catch (Exception ex)
			{
				message = ex.Message;
				return false;
			}
			return true;
		}

		protected bool VerifyLocation(FormGridColumnMeta fgcm, string text, string row)
		{
			//just check to see if there is a location
			//the real check will be to see if there is an outdate if there is no location
			if (text.Length > 0)
				_isLocation = true;
			else
				_isLocation = false;

			return true;
		}

		protected bool VerifyOutDate(FormGridColumnMeta fgcm, string text, string row)
		{
			StringBuilder sb = new StringBuilder();
			string col = fgcm.DisplayName;
			string errMsgKey = row + ":" + col;

			if (this._errMessages.Contains(errMsgKey))
				this._errMessages.Remove(errMsgKey);

			//if there is a location then check for date
			//you cant' have both location and date
			if (_isLocation)
			{
				if (text.Length > 0)
				{
					sb.Append("Row:" + row + "," + "Col:" + col);
					sb.Append(Environment.NewLine);
					sb.Append("Location must be blank if you have an out date!");
					this._errMessages.Add(errMsgKey, sb.ToString());
					return false;
				}
			}
			else
			{
				if (text.Length == 0)
				{
					sb.Append("Row:" + row + "," + "Col:" + col);
					sb.Append(Environment.NewLine);
					sb.Append("You must enter either a location or an out date!");
					this._errMessages.Add(errMsgKey, sb.ToString());
					return false;
				}
				else
				{
					return base.VerifyDate(fgcm, text, row);
				}
			}
			return true;
		}
		#endregion save

		#region get data
		public override void SetEnabled(bool enable)
		{
			GridStyleInfo gsi = null;
			FormGridColumnMeta fgcm = null;

			this._grid.IgnoreReadOnly = true;
			if (enable)
			{
				if (this._grid.RowCount > 0)
				{

					this._btnRemoveBatch.Enabled = true;
					this._btnEditBatch.Enabled = true;
				}
				//enable non-readonly cols
				for (int i = 1; i <= this._grid.ColCount; i++)
				{
					fgcm = (FormGridColumnMeta)this._formGridMeta.GridColumnsOrdered[i - 1];
					gsi = this._grid.ColStyles[i];
					if (!fgcm.ReadOnly)
						gsi.ReadOnly = false;
				}
			}
			else
			{
				//disable non-readonly cols				
				for (int i = 1; i <= this._grid.ColCount; i++)
				{
					fgcm = (FormGridColumnMeta)this._formGridMeta.GridColumnsOrdered[i - 1];
					gsi = this._grid.ColStyles[i];
					if (!fgcm.ReadOnly)
						gsi.ReadOnly = true;
				}
			}
			this._grid.IgnoreReadOnly = false;
		}

		public override bool GetData(int id)
		{
			StringBuilder sb = new StringBuilder();
			//first get the label ids for this batch id
			string sql = "SELECT LabelID From TestReferenceEditBatchSamples " +
				" WHERE BatchID =" + id +
				" ORDER BY LabelID";

			//SqlConnection conn = LoginForm.GetSqlConnection();			
			IDataReader reader = null;

			DataSet ds = new DataSet();
			try
			{
				//conn.Open();
				reader = DataAccess.GetDataReader(sql);

				while (reader.Read())
				{
					MergeDs(reader.GetInt32(0), ds);
				}

				reader.Close();
				_data = ds.Tables[0];
				this._grid.BeginUpdate();
				this._grid.RowCount = 0;

				this._grid.RowCount = _data.Rows.Count;
				int row = 1;
				foreach (DataRow dr2 in _data.Rows)
				{
					//store the dataRow in the cell.tag of the header column
					this._grid[row, 0].Tag = dr2;
					DisplayRow(row, dr2);
					row++;
				}
				this._grid.EndUpdate();
				if (this._grid.RowCount > 0)
					this._btnPrint.Enabled = true;
				else
					this._btnPrint.Enabled = false;

			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
				//TODO - need to do more here for exception				
				MessageBox.Show("GetGridData Exception");
				return false;
			}
			finally
			{
				//if(conn != null)
				//    conn.Dispose();
			}
			return true;

		}

		private void MergeDs(int id, DataSet ds1)
		{
			string sql = "SELECT r.ID, d.Protocol, d.Patient, r.Location, tt.display as Test, " +
				"t.Result, st.display as Sample, r.OutDate, r.Notes " +
				"FROM TestReference r INNER JOIN TestSamples t ON r.ID = t.ID " +
				"INNER JOIN DrawSamples d ON t.DrawSample = d.ID " +
				"INNER JOIN TestType_L tt ON t.TestType = tt.ID " +
				"INNER JOIN SampleType_L st ON d.SampleType = st.ID " +
				" WHERE r.ID =" + id;

			//SqlConnection conn = LoginForm.GetSqlConnection();			
			StringBuilder sb = new StringBuilder();
			try
			{
				DataSet ds = DataAccess.GetDataSet(sql);
				if (ds.Tables.Count > 0)
				{
					ds1.Merge(ds);
				}
			}
			catch (Exception ex)
			{
				sb.Append("Could not GetDataRow for grid!");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "GetDataRow Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			finally
			{
				//if(conn != null)
				//    conn.Dispose();
			}
		}

		protected override void DisplayRow(int row, DataRow dr)
		{
			string message = "";
			for (int i = 1; i < this._grid.ColCount + 1; i++)
			{
				DataColumn dc = (DataColumn)this._grid[0, i].Tag;

				if (this._grid[row, i].CellType == "CheckBox")
				{
					if (dr[dc.ColumnName] != System.DBNull.Value)
					{
						if ((bool)dr[dc.ColumnName])
							this._grid[row, i].CellValue = "1";
						else
							this._grid[row, i].CellValue = "0";
					}
				}
				else
					this._grid[row, i].CellValue = dr[dc.ColumnName];
				if (this._grid[row, i].CellType == "MonthCalendar")
					this._grid[row, i].Format = "MM/dd/yyyy";

				if (dc.ColumnName == "Protocol")
				{
					int protocol = Convert.ToInt32(dr[dc.ColumnName]);
					ProtocolInfo pi = CoreLabUtils.GetProtocolInfo(protocol, out message);
					this._grid[row, i].Tag = pi;
					if (pi.ID > -1)
						this._grid[row, i].CellTipText = pi.GetToolTip();
				}
				if (dc.ColumnName == "Patient")
				{
					int patient = Convert.ToInt32(dr[dc.ColumnName]);
					PatientInfo pi = CoreLabUtils.GetPatientInfo(patient, out message);
					this._grid[row, i].Tag = pi;
					if (pi.ID > -1)
						this._grid[row, i].CellTipText = pi.GetToolTip();
				}
			}
		}
		#endregion get data
	}
}
